package com.blockmeta.bbs.immodule.widget.chatboard;

import android.content.Context;
import android.graphics.Color;
import androidx.appcompat.widget.AppCompatEditText;
import android.text.Editable;
import android.text.Spannable;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.blockmeta.bbs.immodule.Constants.CALL_CHAR;

/*****************************************************************
 * 用于@功能和$等功能的选择end
 ****************************************************************/
public class ChatBoardTagHelper {
    private boolean isInputFreezed = false;

    private int tagStartIndex = 0;
    private int tagEndIndex = 0;

    //多种不同tag和可以tag的对象集合
    private HashMap<String, HashSet<InputFieldQueryItem>> m_mapQueryItem = new HashMap<String, HashSet<InputFieldQueryItem>>();

    private HashMap<String, String> m_mapQueryRule = new HashMap<String, String>();
    //打了tag后需要保存的对象集合
    private HashMap<String, Set<InputFieldQueryItem>> m_mapTagData = new HashMap<String, Set<InputFieldQueryItem>>();
    private HashMap<String, InputFieldQueryAdapter.InputQueryItemMode> m_mapQueryMode = new HashMap<String, InputFieldQueryAdapter.InputQueryItemMode>();

    private PopupQueryList m_popup;

    private int m_TagColor = -1;

    private List<ForegroundColorSpan> m_setColorSpan = new LinkedList<ForegroundColorSpan>();

    private Context mContext;
    private AppCompatEditText mInput;
    private BaseChatBoard.ContentCountListener m_countlistener = null;

    public ChatBoardTagHelper(Context context, AppCompatEditText input) {
        mContext = context;
        mInput = input;
        initializeSymbolList();
    }


    private void initializeSymbolList() {
        m_popup = new PopupQueryList(mContext, 0);
        m_popup.setOnSelectedListener(new PopupQueryList.OnSelectedListener() {
            @Override
            public void onSelected(InputFieldQueryItem pItem) {
                int tStart = mInput.getSelectionStart();
                int tEnd = mInput.getSelectionEnd();
                tStart = tStart == -1 ? 0 : tStart;
                tEnd = tEnd == -1 ? 0 : tEnd;
                tag(pItem.getType(), pItem, tStart, tEnd);
            }

            @Override
            public void onCancel(String msg) {
                //当用户不操作返回的时候需要把特殊字符输入到聊条框
                int tStart = mInput.getSelectionStart();
                int tEnd = mInput.getSelectionEnd();
                mInput.getText().replace(tStart, tEnd, msg);

            }
        });


        mInput.addTextChangedListener(new TextWatcher() {
            private String lastValue = "";

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                String newValue = s.toString();
                if (!newValue.equals(lastValue)) {
                    lastValue = newValue;
                    tagAction();
                }

                try {
                    if (m_countlistener != null) {
                        m_countlistener.onChange(s.length(), s.toString().getBytes("GBK").length);
                    }
                } catch (Exception e) {

                }
            }
        });
    }

    private void tagAction() {
        try {
            if (isInputFreezed) {
                return;
            }

            boolean isOnTag = false;
            int cursorPosition = mInput.getSelectionStart();
            String strBeforeCursor = mInput.getText().toString().substring(0, cursorPosition);

            Set<String> tTagSet = m_mapQueryRule.keySet();

            for (String tTag : tTagSet) {
                int lastIndex = strBeforeCursor.lastIndexOf(tTag);
                if (lastIndex != -1) {
                    String strWithTag = strBeforeCursor.substring(lastIndex);
                    if (strWithTag.matches("\\" + tTag + m_mapQueryRule.get(tTag))) {
                        isOnTag = true;
                        onTag(tTag, strWithTag, lastIndex, lastIndex + strWithTag.length());
                    }
                }
            }

            if (!isOnTag) {
                onNonTag(mInput.getSelectionEnd());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void onTag(String type, String tag, int startIndex, int endIndex) {
        tagStartIndex = startIndex;
        tagEndIndex = endIndex;
        refreshTag();
        mInput.setSelection(tagEndIndex);
    }

    private void onNonTag(int endIndex) {
        tagEndIndex = endIndex;
        refreshTag();
        mInput.setSelection(tagEndIndex);
    }

    public void tag(String pType, String key) {
        int tStart = mInput.getSelectionStart();
        int tEnd = mInput.getSelectionEnd();
        HashSet<InputFieldQueryItem> queryItems = m_mapQueryItem.get(pType);
        if(queryItems != null && queryItems.size() > 0){
            for (InputFieldQueryItem item : queryItems){
                if(item.getKey().equals(key)){
                    tag(pType, item, tStart, tEnd);
                    break;
                }
            }
        }
    }


    private void tag(String pType, InputFieldQueryItem pKey, int pStart, int pEnd) {
        Set<InputFieldQueryItem> tList = m_mapTagData.get(pType);
        tList.add(pKey);
        String replaceTag = pType + pKey.getTag() + " ";
        isInputFreezed = true;
        mInput.getText().replace(pStart, pEnd, replaceTag);
        isInputFreezed = false;
        refreshTag();
        mInput.setSelection(pStart + replaceTag.length());
    }

    /**
     * 刷新tag，当用户输入内容或者删除内容后需要判断tag是否还在继续刷新
     */
    public void refreshTag() {
        isInputFreezed = true;
        String input = mInput.getText().toString();
        Spannable modifiedText = mInput.getText();

        for (ForegroundColorSpan tSpanColor : m_setColorSpan) {
            modifiedText.removeSpan(tSpanColor);
        }
        m_setColorSpan.clear();

        List<InputFieldQueryItem> toRemoveList;
        Set<InputFieldQueryItem> currentList;

        Set<String> tTypeSet = m_mapTagData.keySet();

        for (String tType : tTypeSet) {
            toRemoveList = new ArrayList<InputFieldQueryItem>();
            currentList = m_mapTagData.get(tType);

            for (InputFieldQueryItem tagged : currentList) {
                String tag = tType + tagged.getTag() + " ";
                int startIndex = input.indexOf(tag);
                int lastIndex = startIndex + tag.length() - 1;
                if (startIndex == -1) {
                    toRemoveList.add(tagged);
                } else {
                    String tStrTemp = input;
                    int tStartTemp = startIndex;
                    int tLastTemp = 0;
                    while (tStartTemp != -1) {
                        tStartTemp += tLastTemp;
                        tLastTemp = tStartTemp + tag.length() - 1;
                        ForegroundColorSpan tSpan;
                        if (m_TagColor != -1) {
                            tSpan = new ForegroundColorSpan(m_TagColor);
                        } else {
                            tSpan = new ForegroundColorSpan(Color.BLACK);
                        }
                        modifiedText.setSpan(tSpan, tStartTemp, tLastTemp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        m_setColorSpan.add(tSpan);
                        tStrTemp = input.substring(tLastTemp);
                        tStartTemp = tStrTemp.indexOf(tag);
                    }
                }
            }

            for (InputFieldQueryItem removeTag : toRemoveList) {
                currentList.remove(removeTag);
            }
        }

        isInputFreezed = false;
    }


    public void addType(String pType, String pRule, InputFieldQueryAdapter.InputQueryItemMode pMode, HashSet<InputFieldQueryItem> pHashSet) {
        if (pHashSet == null) {
            m_mapQueryItem.put(pType, new HashSet<InputFieldQueryItem>());
        } else {
            m_mapQueryItem.put(pType, pHashSet);
        }
        m_mapQueryRule.put(pType, pRule);
        m_mapQueryMode.put(pType, pMode);
        m_mapTagData.put(pType, new HashSet<InputFieldQueryItem>());
    }


    public HashMap<String, Set<InputFieldQueryItem>> getTagData() {
        return m_mapTagData;
    }

    public List<ForegroundColorSpan> getTagSpans() {
        return m_setColorSpan;
    }

    public HashMap<String, List<String>> getTagKeyData() {
        HashMap<String, List<String>> tResult = new HashMap<String, List<String>>();
        Set<String> tKeys = m_mapTagData.keySet();
        for (String tKey : tKeys) {
            Set<InputFieldQueryItem> tDataList = m_mapTagData.get(tKey);
            if (tDataList != null) {
                List<String> tList = new ArrayList<String>();
                List<String> tItemKeys = new ArrayList<String>();

                for (InputFieldQueryItem tItem : tDataList) {
                    tList.add(tItem.getTag());
                    tItemKeys.add(tItem.getKey());
                }

                tResult.put(tKey, tList);
                tResult.put(tKey + "KEY", tItemKeys);
            }
        }
        return tResult;
    }

    public Set<InputFieldQueryItem> getTagItemByType(String pType) {
        return m_mapTagData.get(pType);
    }

    public void clearTagData() {
        Set<String> tKeys = m_mapTagData.keySet();
        for (String tKey : tKeys) {
            m_mapTagData.put(tKey, new HashSet<InputFieldQueryItem>());
        }
    }


    public void restoreTagData(HashMap<String, Set<InputFieldQueryItem>> pData) {
        m_mapTagData.putAll(pData);
    }

    public String getInputText(boolean send) {
        String tTxt = mInput.getText().toString();

        ForegroundColorSpan[] spans = mInput.getEditableText().getSpans(0,
                mInput.getEditableText().length(), ForegroundColorSpan.class);
        ArrayList<ForegroundColorSpan> mList = new ArrayList<ForegroundColorSpan>();
        for (int i = 0; i < spans.length; i++) {
            mList.add(spans[i]);
        }
        Collections.sort(mList, new Comparator<ForegroundColorSpan>() {
            @Override
            public int compare(ForegroundColorSpan o1, ForegroundColorSpan o2) {
                return mInput.getText().getSpanStart(o1) < mInput.getText().getSpanStart(o2) ? -1 : 1;
            }
        });
        if (tTxt.length() > 0) {
            if (spans.length > 0) {
                String userDeeplink = "<a href=\"blockmeta://im/user?id=";

                Set<InputFieldQueryItem> userItems = getTagItemByType(CALL_CHAR);

                List<ForegroundColorSpan> tagSpans = getTagSpans();

                Map<String, String> userMap = new HashMap<String, String>();
                for (InputFieldQueryItem item : userItems) {
                    userMap.put(CALL_CHAR + item.getTag(), item.getKey());
                }

                StringBuilder buffer = new StringBuilder();
                int size = spans.length;
                int strIndex = 0; // 普通文本的索引

                for (int i = 0; i < size; i++) {
                    ForegroundColorSpan span = mList.get(i);
                    int start = mInput.getText().getSpanStart(span);
                    int end = mInput.getText().getSpanEnd(span);

                    buffer.append(tTxt.substring(strIndex, start));

                    String name = tTxt.substring(start, end);
                    if (tagSpans.contains(span)) {
                        if (userMap.containsKey(name)) {
                            String key = userMap.get(name);

                            buffer.append(userDeeplink).append(key).append("\">").append(name).append("</a>");

                            buffer.append("\u00A0");
                        }
                    } else {
                        buffer.append(name);
                    }

                    strIndex = end + 1;
                }

                if (strIndex < tTxt.length()) {
                    buffer.append(tTxt.substring(strIndex));
                }

                tTxt = buffer.toString();

                if (tTxt.endsWith("\u00A0")) {
                    tTxt = tTxt.substring(0, tTxt.length() - "\u00A0".length());
                }
            }
        }

        return tTxt;
    }

    public void showPopup(String pTitleHint, String pType) {
        m_popup.show(pTitleHint, m_mapQueryItem.get(pType), m_mapQueryMode.get(pType));
    }
}
